package application

import (
	"context"
	"fmt"
	"github.com/edgexfoundry/edgex-go/internal/app/core/metadata/container"
	"github.com/edgexfoundry/edgex-go/internal/app/dtos/responses"
	"github.com/edgexfoundry/edgex-go/internal/app/models"
	"github.com/edgexfoundry/edgex-go/internal/pkg/correlation"
	bootstrapContainer "github.com/edgexfoundry/go-mod-bootstrap/v2/bootstrap/container"
	"github.com/edgexfoundry/go-mod-bootstrap/v2/di"
	"github.com/edgexfoundry/go-mod-core-contracts/v2/errors"
)

// The DeviceProfileAdd function accepts the new device profile model from the controller functions
// and invokes addDeviceProfile function in the infrastructure layer
func DeviceProfileAdd(d models.DeviceProfile, ctx context.Context, dic *di.Container, deviceId string) (id string, err errors.EdgeX) {
	if deviceId == "" {
		return deviceId, errors.NewCommonEdgeX(errors.KindInvalidId, "device id invalid", err)
	}

	dbClient := container.DBClientFrom(dic.Get)
	lc := bootstrapContainer.LoggingClientFrom(dic.Get)

	correlationId := correlation.FromContext(ctx)
	id, err = dbClient.DeviceProfileAdd(deviceId, d)
	if err != nil {
		return "", errors.NewCommonEdgeXWrapper(err)
	}

	lc.Debugf(
		"DeviceProfile created on DB successfully. DeviceProfile-id: %s, Correlation-id: %s ",
		id,
		correlationId,
	)

	return id, nil
}

// DeviceProfileById query the device profile by name
func DeviceProfileById(id string, ctx context.Context, dic *di.Container) (deviceProfile models.DeviceProfile, err errors.EdgeX) {
	if id == "" {
		return deviceProfile, errors.NewCommonEdgeX(errors.KindContractInvalid, "id is empty", nil)
	}
	dbClient := container.DBClientFrom(dic.Get)
	deviceProfile, err = dbClient.DeviceProfileById(id)
	if err != nil {
		return deviceProfile, errors.NewCommonEdgeXWrapper(err)
	}
	return
}

// SyncDeviceProfileById 同步设备元信息
func SyncDeviceProfileById(id string, ctx context.Context, dic *di.Container) {

	lc := bootstrapContainer.LoggingClientFrom(dic.Get)
	if id == "" {
		lc.Errorf(
			"SyncDeviceProfileById failed. Because of device id is nil",
			id,
		)
	}

	dbClient := container.DBClientFrom(dic.Get)
	profile, err := dbClient.SyncDeviceProfileById(id)
	if err != nil {
		lc.Errorf(
			fmt.Sprintf("SyncDeviceProfileById failed. Because of %v", err),
			id,
		)
	}

	lc.Errorf(
		"SyncDeviceProfileById success. ",
		id,
	)

	go updateDeviceProfileCallback(ctx, dic, responses.ToDeviceProfileDTO(profile))
	return
}
